package com.zx.security.reactive.handle;

import com.zx.core.constant.TokenConstants;
import com.zx.core.utils.ServletUtils;
import com.zx.core.wrapper.ResponseWrapper;
import com.zx.security.reactive.service.ICustomTokenService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.logout.ServerLogoutHandler;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;


/**
 * <p>
 * description: 注销处理类 <br>
 * create: 2024-08-15 16:47
 * </p>
 *
 * @author zhou  xun
 */
@Component
@Slf4j
public class LogoutSuccessHandlerImpl implements ServerLogoutHandler {

    @Autowired
    ICustomTokenService iCustomTokenService;

    /**
     * 在请求注销时调用
     *
     * @param exchange       the exchange
     * @param authentication the {@link Authentication}
     * @return a completion notification (success or error)
     */
    @Override
    public Mono<Void> logout(WebFilterExchange exchange, Authentication authentication) {
        return Mono.defer(() -> {
            ResponseWrapper result = new ResponseWrapper();
            ServerHttpResponse response = exchange.getExchange().getResponse();
            response.setStatusCode(HttpStatus.OK);
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            //获取token,删除用户缓存记录
            String token = exchange.getExchange().getRequest().getHeaders().getFirst(TokenConstants.AUTHENTICATION);
            String tokenWithoutPrefix = StringUtils.isNotEmpty(token) && token.startsWith(TokenConstants.PREFIX) ? token.substring(TokenConstants.PREFIX.length()) : token;
            return iCustomTokenService.getLoginUser(tokenWithoutPrefix)
                    .flatMap(loginUser -> {
                        if (loginUser != null) {
                            // 删除用户缓存记录
                            return iCustomTokenService.delLoginUser(tokenWithoutPrefix);
                        }
                        return Mono.empty();
                    })
                    .then(Mono.defer(() -> {
                        DataBuffer buffer = ServletUtils.getDataBuffer(result, response.bufferFactory());
                        return response.writeWith(Mono.just(buffer))
                                .doFinally(signalType -> DataBufferUtils.release(buffer));
                    }))
                    .onErrorResume(ex -> {
                        // 统一的错误处理
                        log.error("注销时出错", ex);
                        result.fail(ex.getMessage());
                        DataBuffer errorBuffer = ServletUtils.getDataBuffer(result, response.bufferFactory());
                        return response.writeWith(Mono.just(errorBuffer))
                                .doFinally(signalType -> DataBufferUtils.release(errorBuffer));
                    });
        });
    }

}
